﻿using System;
using System.Collections.Generic;
using System.Text;

namespace XP.Utilities.Utility
{
    public class MyMath
    {
        /// <summary>
        /// 根据几率列表和索引列表获取指定长度的列表
        /// </summary>
        /// <param name="returnLength">返回的数据长度</param>
        /// <param name="allowRepeat">是否允许重复的索引</param>
        /// <param name="nums">索引列表</param>
        /// <param name="probabilities">几率列表</param>
        /// <param name="rnd">随机对象</param>
        /// <returns></returns>
        public static List<string> GetRandomNums(int returnLength, bool allowRepeat, string[] nums, double[] probabilities, ref Random rnd)
        {
            double minRate = Max(probabilities);
            double maxRate = Min(probabilities);
            if (minRate <= 0) minRate = 0.1;
            else minRate = MinusNumber(minRate, 1);
            List<string> result = new List<string>();
            List<string> finedList = new List<string>();
            for (int i = 0; i < returnLength; i++)
            {
                double rndNum = AverageRandom(minRate, maxRate, ref rnd);
                List<string> findList = new List<string>();
                for (int n = 0; n < probabilities.Length; n++)
                {
                    if (probabilities[n] >= rndNum)
                    {
                        findList.Add(nums[n]);
                    }
                }
                if (findList.Count > 0)
                {
                    int retryTimes = 0;
                GetResult:
                    int rndIndex = rnd.Next(0, findList.Count);
                    string findIndex = findList[rndIndex];
                    if (!allowRepeat && result.Contains(findIndex))
                    {
                        if (retryTimes < 5)
                        {
                            retryTimes++;
                            goto GetResult;
                        }
                        else
                        {
                            i--;
                        }
                    }
                    else
                    {
                        result.Add(findIndex);
                    }
                }
                else
                {
                    i--;
                }
            }
            return result;
        }
        /// <summary>
        /// 在指定的Number基础上减去指定数值的最小值
        /// </summary>
        /// <param name="number">被减去的数值，如:90.1</param>
        /// <param name="minusNumber">减去多少数值，如：1</param>
        /// <returns>减好的数值,如:90.09</returns>
        static double MinusNumber(double number, double minusNumber)
        {
            if (number <= 0) return 0.1;
            if (number.ToString().IndexOf(".") == -1)
            {
                return number - minusNumber / 10;
            }
            StringBuilder aStr = new StringBuilder(number.ToString());
            for (int i = aStr.Length - 1; i > 0; i--)
            {
                if (aStr[i] == '0')
                    aStr.Remove(i, 1);
                else
                {
                    break;
                }
            }
            int length = aStr.ToString().Split('.')[1].Length;
            return number - (minusNumber / (Math.Pow(10, length)));
        }

        static double AverageRandom(double min, double max, ref Random rnd)
        {
            double dResult = rnd.NextDouble() * (max - min) + min;
            return dResult;
        }

        static double Max(double[] probabilities)
        {
            double maxValue = 0;
            for (int i = 0; i < probabilities.Length; i++)
            {
                if (probabilities[i] > maxValue) maxValue = probabilities[i];
            }
            return maxValue;
        }
        static double Min(double[] probabilities)
        {
            double minValue = 0;
            for (int i = 0; i < probabilities.Length; i++)
            {
                if (probabilities[i] < minValue) minValue = probabilities[i];
            }
            return minValue;
        }
    }
}
